package cn.wolfcode.p2p.business.service.impl;

import cn.wolfcode.base.QueryObject;
import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.domain.LoginInfo;
import cn.wolfcode.p2p.base.domain.UserInfo;
import cn.wolfcode.p2p.base.exception.CustomerException;
import cn.wolfcode.p2p.base.mapper.LoginInfoMapper;
import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.base.service.IUserInfoService;
import cn.wolfcode.p2p.base.util.BidConst;
import cn.wolfcode.p2p.base.util.BitStateUtil;
import cn.wolfcode.p2p.base.util.DateUtil;
import cn.wolfcode.p2p.base.util.UserContext;
import cn.wolfcode.p2p.business.domain.Bid;
import cn.wolfcode.p2p.business.domain.BidRequest;
import cn.wolfcode.p2p.business.domain.BidRequestAuditHistory;
import cn.wolfcode.p2p.business.mapper.BidRequestAuditHistoryMapper;
import cn.wolfcode.p2p.business.mapper.BidRequestMapper;
import cn.wolfcode.p2p.business.query.BidRequestQuery;
import cn.wolfcode.p2p.business.service.IBidRequestService;
import cn.wolfcode.p2p.business.util.CalculatetUtil;
import cn.wolfcode.p2p.business.vo.PublishAuditVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class BidRequestServiceImpl implements IBidRequestService {
    @Autowired
    private BidRequestMapper bidRequestMapper;
    @Autowired
    private BidRequestAuditHistoryMapper bidRequestAuditHistoryMapper;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IUserInfoService userInfoService;
    @Autowired
    private LoginInfoMapper loginInfoMapper;


    @Override
    public BidRequest get(Long id) {
        return bidRequestMapper.selectById(id);
    }

    @Override
    public List<BidRequestAuditHistory> listAuditHistorysByBidRequestId(Long bidRequestId) {
        return bidRequestAuditHistoryMapper.selectByBidRequestId(bidRequestId);
    }

    @Override
    @Transactional(readOnly = true)
    public PageInfo<BidRequest> query(QueryObject qo) {
        PageHelper.startPage(qo.getCurrentPage(), qo.getPageSize());
        List<BidRequest> list = bidRequestMapper.selectList(qo);
        return new PageInfo<BidRequest>(list);
    }

    public void update(BidRequest entity) {
        // 乐观锁,当更新行数为0时,则表示更新失败
        int rows = bidRequestMapper.updateById(entity);
        if (rows == 0) {
            throw new CustomerException("乐观锁失败:BidRequest.id" + entity.getId());
        }
    }

    @Override
    public BidRequest getByCreateUserId(Long createUserId) {
        return bidRequestMapper.selectByCreateUserId(createUserId);
    }

    @Override
    public void apply(BidRequest vo) {
        UserInfo current = userInfoService.getCurrent();
        Account account = accountService.getCurrent();
        // 1.非法判断(填写数据的判断/是否存在一个借款申请)
        if (
                current.getBorrowable() // 满足借款条件
                        && !current.getHasRequestInProcess() // 不存在借款申请
                        && vo.getBidRequestAmount().compareTo(BidConst.MIN_BIDREQUEST_AMOUNT) >= 0
                        && vo.getBidRequestAmount().compareTo(account.getRemainBorrowLimit()) <= 0
                        && vo.getCurrentRate().compareTo(BidConst.MIN_CURRENT_RATE) >= 0
                        && vo.getCurrentRate().compareTo(BidConst.MAX_CURRENT_RATE) <= 0
                        && vo.getMinBidAmount().compareTo(BidConst.MIN_BID_AMOUNT) >= 0
        ) {
            // 2.创建BidRequest对象,设置相关数据,并保存
            BidRequest br = new BidRequest();
            br.setBidRequestType(BidConst.BIDREQUEST_TYPE_NORMAL);
            br.setReturnType(BidConst.RETURN_TYPE_MONTH_INTEREST_PRINCIPAL);
            br.setBidRequestState(BidConst.BIDREQUEST_STATE_APPLY);
            br.setBidRequestAmount(vo.getBidRequestAmount());
            br.setCurrentRate(vo.getCurrentRate().divide(new BigDecimal("100"), 4, BigDecimal.ROUND_HALF_UP));
            br.setMinBidAmount(vo.getMinBidAmount());
            br.setMonthes2return(vo.getMonthes2return());
            br.setBidCount(0);
            br.setCurrentSum(BidConst.ZERO);
            br.setTitle(vo.getTitle());
            br.setDescription(vo.getDescription());
            br.setDisableDays(vo.getDisableDays());
            br.setApplyTime(new Date());
            br.setCreateUser(UserContext.getCurrentUser());
            br.setBids(new ArrayList<Bid>());
            // 借款总利息
            br.setTotalRewardAmount(CalculatetUtil.calTotalInterest(
                    br.getReturnType()
                    , br.getBidRequestAmount()
                    , br.getCurrentRate()
                    , br.getMonthes2return()
            ));
            bidRequestMapper.insert(br);
            // 3.给当前用户增加借款中的状态码,更新用户信息
            current.setBitState(current.getNewState(BitStateUtil.OP_HAS_BIDREQUEST_PROCESS));
            userInfoService.update(current);

        }
        //==========================================================
        // 0.判断是否有正在进行的借款,以及当前用户认证是否通过
//        if (!current.getBorrowable()) {
//            throw new CustomerException("当前用户未认证通过,前先进行认证");
//        }
//        // 0.1是否有正在进行的借款
//
//        // 1.当前申请借款今天与申请用户可用的借款金额比较,超过可借款范围则不能申请(比最低额度大,比最大限额小)
//        Account currentAccount = accountService.getCurrent();
//        if (!(vo.getBidRequestAmount().compareTo(currentAccount.getRemainBorrowLimit()) == -1
//                && vo.getBidRequestAmount().compareTo(BidConst.MIN_BIDREQUEST_AMOUNT) == 1)
//        ) {
//            throw new CustomerException("亲,借款额度不符要求,请调整后提交");
//        }
        // 1.1计算当前总利息
//        BigDecimal totalRewardAmount = CalculateUtil.cal(vo.getReturnType(),vo.getBidRequestAmount(), vo.getMonthes2return(), vo.getCurrentRate());
//        if (!(totalRewardAmount.compareTo(BidConst.MIN_CURRENT_RATE) == 1
//                && totalRewardAmount.compareTo(BidConst.MAX_CURRENT_RATE) == -1)
//        ) {
//            throw new CustomerException("亲,借款利率不符要求,请调整后提交");
//        }
        // 2.如果可以申请需要进一步判断前台传值是否存在,要严格校验(标签代替)
//        BigDecimal totalRewardAmount = vo.getCurrentRate().divide(new BigDecimal("100"), 4).divide(new BigDecimal("12"), 4)
//                .multiply(new BigDecimal(vo.getMonthes2return()));
        // 3.校验通过之后,需要创建BidRequest,并保存该条借款申请
        // 需要计算招标截止日期,设置申请时间,设置总回报金额(总利息)
//        BidRequest bidRequest = new BidRequest();
        // 计算招标截止时间
//        Date disableDate = DateUtils.addDays(new Date(), vo.getDisableDays());
//        bidRequest.setBidRequestType(BidConst.BIDREQUEST_TYPE_NORMAL)
//                .setReturnType(vo.getReturnType())
//                .setBidRequestState(BidConst.BIDREQUEST_STATE_APPLY)
//                .setBidRequestAmount(vo.getBidRequestAmount())
//                .setCurrentRate(vo.getCurrentRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP))
//                .setMinBidAmount(vo.getMinBidAmount())
//                .setMonthes2return(vo.getMonthes2return())
//                .setBidCount(0)
//                .setTotalRewardAmount(totalRewardAmount)
//                .setTotalRewardAmount(new BigDecimal("1"))
//                .setCurrentSum(BidConst.ZERO)
//                .setTitle(vo.getTitle())
//                .setDescription(vo.getDescription())
//                .setDisableDate(disableDate)
//                .setApplyTime(new Date())
//                .setDisableDays(vo.getDisableDays())
//                .setCreateUser(UserContext.getCurrentUser())
//        ;
//        bidRequestMapper.insert(bidRequest);
        // 4.同时还需要为当前用户更新状态:借款申请中
//        current.setBitState(current.getNewState(BitStateUtil.OP_HAS_BIDREQUEST_PROCESS));
//        userInfoService.update(current);
    }

    @Override
    public void audit(PublishAuditVO vo) {
        // 1.判断当前发标的状态是否处于发标前审核,根据bidRequest的id查出当前标的状态
        BidRequest bidRequest = bidRequestMapper.selectById(vo.getId());
        LoginInfo applier = loginInfoMapper.selectById(bidRequest.getCreateUser().getId()); // 借款人
        UserInfo applierUser = userInfoService.get(bidRequest.getCreateUser().getId());
        if (bidRequest.getBidRequestState() == BidConst.BIDREQUEST_STATE_APPLY) {
            // 2.设置审核参数到历史纪录中
            BidRequestAuditHistory history = new BidRequestAuditHistory();
            history.setBidRequestId(vo.getId());
            history.setAuditType(BidRequestAuditHistory.PUBLISH_AUDIT);
            history.setState(vo.getState());
            history.setRemark(vo.getRemark());
            history.setAuditTime(new Date());
            history.setApplyTime(bidRequest.getApplyTime());
            history.setAuditor(UserContext.getCurrentUser());
            history.setApplier(applier);
            // 2.1 判断审核通过,要更新当前标的发布状态,
            if (vo.getState() == BidRequestAuditHistory.STATE_PASS) {
                Date publishTime = vo.getPublishTime();
                Date disableDate = DateUtils.addDays(publishTime, bidRequest.getMonthes2return());
                bidRequest.setPublishTime(publishTime)
                        .setDisableDate(disableDate);
                applierUser.setBitState(BitStateUtil.addState(applierUser.getBitState(), BidConst.BIDREQUEST_STATE_APPROVE_PENDING_1));
            } else if (vo.getState() == BidRequestAuditHistory.STATE_REJECT) {
                //审核拒绝 要将当前申请人状态码移除申请借款的状态
                applierUser.setBitState(
                        BitStateUtil.removeState(applierUser.getBitState(), BidConst.BIDREQUEST_STATE_APPLY)
                );

            }
            // 2.2 新增审核历史
            bidRequestAuditHistoryMapper.insert(history);
        }
        // 3.更新当前bidRequest
        this.update(bidRequest);
        // 4.更新用户状态信息
        userInfoService.update(applierUser);
    }

    // 处理过时间问题的,时分数据,不需要秒
    @Override
    public void publishAudit(Long id, int state, String remark, String publishTime) {
        // 1.判断当前发标的状态是否处于发标前审核,根据bidRequest的id查出当前标的状态,处于借款申请中
        BidRequest bidRequest = bidRequestMapper.selectById(id);
        LoginInfo applier = loginInfoMapper.selectById(bidRequest.getCreateUser().getId()); // 借款人
        UserInfo applierUser = userInfoService.get(bidRequest.getCreateUser().getId());
        if (bidRequest != null && bidRequest.getBidRequestState() == BidConst.BIDREQUEST_STATE_APPLY) {
            // 2.设置审核参数到历史纪录中
            BidRequestAuditHistory history = new BidRequestAuditHistory();
            history.setBidRequestId(id);
            history.setAuditTime(new Date());
            history.setApplyTime(bidRequest.getApplyTime());
            history.setAuditor(UserContext.getCurrentUser());
            history.setApplier(applier);

            history.setAuditType(BidRequestAuditHistory.PUBLISH_AUDIT); // 发标前审核
            history.setState(state);
            history.setRemark(remark);
            // 保存审核历史
            bidRequestAuditHistoryMapper.insert(history);
            // 2.1 判断审核通过,要更新当前标的发布状态,

            if (state == BidRequestAuditHistory.STATE_PASS) {
                // 2.1.1判断publishTime == null 立刻发标,招标中
                if (!StringUtils.hasLength(publishTime)) {
                    bidRequest.setPublishTime(new Date());
                    bidRequest.setBidRequestState(BidConst.BIDREQUEST_STATE_BIDDING);
                } else {
                    // 2.1.2判断publishTime != null 定时发标,待发布
                    bidRequest.setPublishTime(DateUtil.string2date(publishTime, "yyyy-MM-dd HH:mm"));
                    bidRequest.setBidRequestState(BidConst.BIDREQUEST_STATE_PUBLISH_PENDING);

                }
                bidRequest.setNote(remark);
                Date disableDate = DateUtils.addDays(bidRequest.getPublishTime(), bidRequest.getDisableDays());
                bidRequest.setDisableDate(disableDate);

                applierUser.setBitState(BitStateUtil.addState(applierUser.getBitState(), BidConst.BIDREQUEST_STATE_APPROVE_PENDING_1));
            } else if (state == BidRequestAuditHistory.STATE_REJECT) {
                //审核拒绝 要将当前申请人状态码移除申请借款的状态,借款状态为发标拒绝,取消借款人中借款的状态
                bidRequest.setNote(remark);
                bidRequest.setBidRequestState(BidConst.BIDREQUEST_STATE_PUBLISH_REFUSE);
                applierUser.setBitState(
                        BitStateUtil.removeState(applierUser.getBitState(), BitStateUtil.OP_HAS_BIDREQUEST_PROCESS)
                );
            }
        }

        // 3.更新当前bidRequest
        this.update(bidRequest);
        // 4.更新用户状态信息
        userInfoService.update(applierUser);
    }

    @Override
    public List<BidRequest> listIndexBidRequests(int number) {
        BidRequestQuery qo = new BidRequestQuery();
        qo.setStates(new int[]{
                BidConst.BIDREQUEST_STATE_BIDDING,
                BidConst.BIDREQUEST_STATE_PAYING_BACK,
                BidConst.BIDREQUEST_STATE_COMPLETE_PAY_BACK
        });
        qo.setOrderByBidRequestStateAsc(true);
        PageHelper.startPage(1, number);
//        PageHelper.startPage(1, number, "br.bid_request_state asc,br.publish_time desc");
        return bidRequestMapper.selectList(qo);
    }

}
